#include "ws_client_app.hpp"
#include <websocketpp/config/asio_no_tls_client.hpp>
#include <websocketpp/client.hpp>
#include <iostream>
#include "sorfttimer_v2.hpp"
#include "app.hpp"

typedef websocketpp::client<websocketpp::config::asio_client> client;

using namespace std;
using websocketpp::lib::bind;
using websocketpp::lib::placeholders::_1;
using websocketpp::lib::placeholders::_2;

// pull out the type of messages sent by our config
typedef websocketpp::config::asio_client::message_type::ptr message_ptr;

#define SERVER_DEBUG_MODE 1

client *ws_client = nullptr;

websocketpp::connection_hdl connect_handle;

void ws_send_text_data_to_server(std::string str)
{
    if ((ws_client != nullptr) && connect_handle.expired()) /*检查handle是否有效*/
    {
        return;
    }
    try
    {
        ws_client->send(connect_handle, str, websocketpp::frame::opcode::text);
    }
    catch (websocketpp::exception const &e)
    {
#if SERVER_DEBUG_MODE
        std::cout << "Echo failed because: "
                  << "(" << e.what() << ")" << std::endl;
#endif
    }
}

// This message handler will be invoked once for each incoming message. It
// prints the message and then sends a copy of the message back to the server.
void on_message(client *c, websocketpp::connection_hdl hdl, message_ptr msg)
{
    std::cout << "on_message called with hdl: " << hdl.lock().get()
              << " and message: " << msg->get_payload()
              << std::endl;

    // websocketpp::lib::error_code ec;

    // c->send(hdl, msg->get_payload(), msg->get_opcode(), ec);
    // if (ec)
    // {
    //     std::cout << "Echo failed because: " << ec.message() << std::endl;
    // }
}

/**
 * 用于连接的回调函数
 */
void on_open(websocketpp::connection_hdl hdl)
{
    connect_handle = hdl;

    st_start_cb_timer(APP_TASK_CONNECT, 30, TIM_LOCK, TIM_ONCE, app_task_process);

#if SERVER_DEBUG_MODE
    // std::cout << "Connection opened" << std::endl;
#endif
}

/**
 * 用于断开的回调函数
 **/
void on_close(websocketpp::connection_hdl hdl)
{
    connect_handle.reset();
    st_start_cb_timer(APP_TASK_DISCONNECT, 30, TIM_LOCK, TIM_ONCE, app_task_process);
#if SERVER_DEBUG_MODE
    // std::cout << "Connection closed" << std::endl;
#endif
}

int ws_client_process(void)
{
    // Create a client endpoint

    std::string uri = "ws://192.168.1.33:9002";

    if (ws_client == nullptr)
    {
        ws_client = new client();
    }

    try
    {
        // Set logging to be pretty verbose (everything except message payloads)
        ws_client->set_access_channels(websocketpp::log::alevel::all);
        ws_client->clear_access_channels(websocketpp::log::alevel::frame_header); /*清除帧头日志*/
        ws_client->clear_access_channels(websocketpp::log::alevel::frame_payload);

        // Initialize ASIO
        ws_client->init_asio();

        // Register our message handler
        ws_client->set_message_handler(bind(&on_message, ws_client, ::_1, ::_2));

        ws_client->set_open_handler(on_open);

        ws_client->set_close_handler(on_close);

        websocketpp::lib::error_code ec;
        client::connection_ptr con = ws_client->get_connection(uri, ec);
        if (ec)
        {
            std::cout << "could not create connection because: " << ec.message() << std::endl;
            return 0;
        }

        // Note that connect here only requests a connection. No network messages are
        // exchanged until the event loop starts running in the next line.
        ws_client->connect(con);

        // Start the ASIO io_service run loop
        // this will cause a single connection to be made to the server. ws_client.run()
        // will exit when this connection is closed.
        ws_client->run();
    }
    catch (websocketpp::exception const &e)
    {
        std::cout << e.what() << std::endl;
        delete ws_client;
        ws_client = nullptr;
        return 1;
    }

    delete ws_client;
    ws_client = nullptr;
    return 0;
}